package org.zezs.sync.mongo.dataProess;

import com.alibaba.fastjson.JSONObject;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import org.bson.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zezs.sync.mongo.Constants;
import org.zezs.sync.mongo.RunTimeUtil;
import org.zezs.sync.mongo.config.sync.metadata.Chains;
import org.zezs.sync.mongo.config.sync.metadata.Mappings;
import org.zezs.sync.mongo.config.sync.metadata.SyncEnt;

import javax.script.ScriptException;
import java.util.*;

public class DefaultJsProesser implements Proesser {
    Logger logger = LoggerFactory.getLogger(DefaultJsProesser.class);

    @Override
    public List<JSONObject> proess(Chains chains, List<Document> querResult) {

        List<JSONObject> batchData = new ArrayList<>();
        SyncEnt syncEnt = chains.getRef_syncEnt();
        Object apiScript = RunTimeUtil.getJsRunTimeUtil(syncEnt).getEngine().get("apiScript");
        Object content=null;
        try {
            content = RunTimeUtil.getJsRunTimeUtil(syncEnt).getEngine().invokeMethod(apiScript, chains.hashCode() + "",
                    new Object[]{querResult});
        } catch (ScriptException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        if (content == null) {
            logger.error("js 函数转换数据失败");
            throw  new RuntimeException("转换数据失败");
        } else if (content instanceof ScriptObjectMirror) {
            ScriptObjectMirror scriptObjectMirror = (ScriptObjectMirror) content;
            if( scriptObjectMirror.isArray()){
                Collection<Object> values = scriptObjectMirror.values();
                values.forEach(o -> {
                    JSONObject jsonResult = new JSONObject();
                    ScriptObjectMirror jsObj = (ScriptObjectMirror) o;
                    Set<Map.Entry<String, Object>> entrySet = jsObj.entrySet();
                    for (Map.Entry<String, Object> entry : entrySet) {
                        jsonResult.put(entry.getKey(), entry.getValue());
                    }
                    List<Mappings> mappings = chains.getMappings();


                    Document data = (Document) jsObj.get("data");
                    if(data==null){
                        logger.error("为了支持同步，js脚本请返回数组对象字段包含 data 值为原始记录对象");
                        throw  new RuntimeException("为了支持同步，js脚本请返回数组对象字段包含 data 值为原始记录对象");
                    }
                    for (int i = 0; i < mappings.size(); i++) {
                        Mappings mappings2 = mappings.get(i);
                        String sourceField = mappings2.getSourceField();
                        String mapppingKey = mappings2.getDestField() == null ? mappings2.getSourceField()
                                : mappings2.getDestField();
                        Object mappingValue = RunTimeUtil.getDest(mappings2, sourceField == null ? null : data.get(sourceField));
                        jsonResult.put(mapppingKey, mappingValue);
                    }
                    jsonResult.put(Constants.mongoId, data.getObjectId("_id").toString());

                    batchData.add(jsonResult);
                });
            }else{
                logger.error("目前支持批量同步，js脚本请返回数组对象");
                throw  new RuntimeException("目前支持批量同步，js脚本请返回数组对象");
            }

        }
        return batchData;
    }
}
